//=============================================================================
// Copyright 2006-2010 Daniel W. Dyer
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//=============================================================================
package org.dmgenie.mtech.ke.ga.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.uncommons.maths.random.MersenneTwisterRNG;
import org.uncommons.maths.random.PoissonGenerator;
import org.uncommons.watchmaker.examples.EvolutionLogger;
import org.uncommons.watchmaker.framework.CandidateFactory;
import org.uncommons.watchmaker.framework.EvolutionaryOperator;
import org.uncommons.watchmaker.framework.GenerationalEvolutionEngine;
import org.uncommons.watchmaker.framework.SelectionStrategy;
import org.uncommons.watchmaker.framework.factories.ListPermutationFactory;
import org.uncommons.watchmaker.framework.operators.EvolutionPipeline;
import org.uncommons.watchmaker.framework.operators.ListOrderCrossover;
import org.uncommons.watchmaker.framework.operators.ListOrderMutation;
import org.uncommons.watchmaker.framework.selection.RankSelection;
import org.uncommons.watchmaker.framework.termination.TargetFitness;

import org.dmgenie.mtech.ke.ga.util.*;


public class LoadDistribution
{
    public static void main(String[] args)
    {
        evolveList();
    }


    public static List<Integer> evolveList()
    {
    	boolean crossover = true;
    	boolean mutation = true;
    	Random rng = new MersenneTwisterRNG();
    	// Set-up evolution pipeline (cross-over followed by mutation).
        List<EvolutionaryOperator<List<Integer>>> operators = new ArrayList<EvolutionaryOperator<List<Integer>>>(2);
        if (crossover)
        {
            operators.add(new ListOrderCrossover<Integer>());
        }
        if (mutation)
        {
            operators.add(new ListOrderMutation<Integer>(new PoissonGenerator(1.5, rng),
                                                        new PoissonGenerator(1.5, rng)));
        }
        EvolutionaryOperator<List<Integer>> pipeline = new EvolutionPipeline<List<Integer>>(operators);
        
        List<Integer> packageIds = new ArrayList<Integer>(); 
        for (int i=0; i<64; i++) {//HARDCODED
        	packageIds.add(i);//putting the package id as 0 to 63
        }
        CandidateFactory<List<Integer>> candidateFactory = new ListPermutationFactory<Integer>(packageIds);
        
        SelectionStrategy selectionStrategy = new RankSelection();
        
        GenerationalEvolutionEngine<List<Integer>> engine = 
        		new GenerationalEvolutionEngine<List<Integer>>
        			(candidateFactory,
	                   pipeline,
	                   new FitnessLogEvaluator(),
	                   selectionStrategy,
	                   rng);
        
//        engine.setSingleThreaded(singleThreaded)SingleThreaded(true); // Performs better for very trivial fitness evaluations.
        engine.addEvolutionObserver(new EvolutionLogger<List<Integer>>());
        
        List<Integer> results = engine.evolve(100, // 100 individuals in each generation.
                10, 
                new TargetFitness(3, false)); // Continue until a perfect match is found. 
        System.out.println(results.toString());
        return results;       
    }
}
